1. Field of the Invention
This invention relates to the field of computer-related systems, and more particularly to shared objects in an object-oriented environment.
2. Background Art
In the development of software applications, it is becoming more common for separate applications to interact with each other such that data processed in one application is accessed from another application as well, and possibly further processed. The utility of each application is increased by its inclusion in a suite of related applications that each provide some function with respect to the common data. Mechanisms exist for sharing data by encapsulating the data in objects which are shared among the applications. One application creates the object, and then other applications are able to obtain a reference to the object and share its data via the methods or interfaces provided by the shared object.
However, each shared object is owned by the host application that created it. This means that the shared object resides within the host application, and that, when the host application shuts down, all of its associated shared objects are terminated, depriving all other applications of access to the shared data. Also, all applications access the shared object indirectly via the host application. This indirect access of the shared object is many times slower, and much more expensive in processor resources, than direct access to the object. There is therefore a shutdown problem and a performance problem inherent in this mechanism for sharing objects between applications. To better illustrate the problems associated with sharing objects, description is given below with respect to application process spaces and one software technology which facilitates the sharing of objects, the object linking and embedding (OLE) technology from. Microsoft Corporation, built upon the component object model (COM).
Application Process Spaces and OLE/COM
Each application or process has its own assigned xe2x80x9cprocess spacexe2x80x9d comprised of logical addresses. Each process is assigned random access memory (RAM) comprising those locations in random access memory that are accessible to the given process (i.e., address space). Logical addresses in each process space are mapped to actual physical addresses of random-access memory independently of any other process space. For example, logical (or process) addresses 0-1800 for process space A. may be mapped to physical addresses 700-2500, whereas logical addresses 0-1800 of process space B may be mapped to physical addresses 2501-2801 and 3000-4500. A logical address of 300 within process space A maps to a completely different and independent location in RAM than the same logical address within process space B.
Operations or function calls which occur within a single process are commonly referred to as xe2x80x9cin-processxe2x80x9d calls, whereas function calls which involve crossing the process boundary to be completed in a separate process space are commonly referred to as xe2x80x9ccross-processxe2x80x9d calls. The OLE/COM system typically manages cross-process calls by marshalling the calls using an LRPC (lightweight remote procedure call) packet mechanism.
When a client process issues a cross-process function call directed to a server process across a process boundary, the remoting code of the OLE/COM system (e.g., an object proxy) marshals the function call on the client side, including generation of a marshal packet. The system processor then performs a context switch to transfer operation from the client process to the server process. On the server side, further code for remoting the function call(e.g., stub code) unmarshals the marshal packet and initiates the function callin the server process. Any returned response from the server process is similarly marshalled back to the client process with the associated context switch from server process to client process.
In contrast, in-process function calls are processed directly, without the need for marshalling or context switching. As a result, cross-process function calls may be up to 1000 times slower than in-process function calls. Unfortunately, the sharing of objects in the OLE/COM system is strongly dependent on cross-process function calls.
FIG. 1A illustrates the system structure of an OLE/COM system. System hardware 106, such as a personal computer, is used to execute and support an operating system 105, such as the windows NT or other available operating systems. The OLE 103 and COM 104 software subsystems execute on top of the operating system and form a platform for the creation, management and interaction of OLE/COM objects. Processes 100-102 operate on top of this OLE/COM platform.
The OLE/COM system includes an API (application programming interface) supporting calls for services such as standard marshalling, and proxy/stub pair remoting code defined using IDL (interface definition language) is maintained to service standard marshalling calls. The OLE/COM system includes an object server registry for locating an appropriate object server for a given object class ID. Information regarding what methods an interface supports, and the types of parameters required by each method, may be obtained from a type library.
OLE/COM objects comprise one or more interfaces by which object methods may be invoked. Each interface represents a contract between the client accessing the interface and the object serving the interface. Every OLE/COM object includes the IUnknown interface, which, when queried, provides information about the other interfaces supported by the respective object. The interfaces of an OLE/COM object are identified by pointers in a pointer table. These pointers have meaning only within the process space in which the object is created, or instantiated.
Object data is encapsulated within the object and is accessed via the supported interfaces. One piece of data that exists within each OLE/COM object is a reference count. The reference count is incremented for every new reference to the object, and decremented when a reference is no longer in use. The object can be terminated and its resources released when the reference count is at zero, or when the host process itself terminates. Objects may be created by class factories of an object server resident within a process space or an object server resident within a dynamic linked library (DLL) appended to a process space.
Cross-Process Object Sharing
Sharing dynamically created objects across multiple process spaces is a difficult problem to solve in a generic sense. OLE/COM supports the following object sharing mechanisms shown in FIGS. 2A-2C.
FIG. 2A illustrates two processes, process A and process B, residing in respective process spaces 200 and 201. Between process spaces 200 and 201 is a conceptual process boundary representing a separation between independent process spaces 200 and 201. Object 202 is instantiated within process A, with all associated pointers to interfaces defined with respect to process space 200. Process A is considered to xe2x80x9cownxe2x80x9d object 202, because object 202 exists only within the process in which it is instantiated. All calls on the interfaces of object 202 from process A are made as direct, in-process function calls.
However, if another process, process B, somehow acquires a reference to object 202, the OLE/COM system instantiates a proxy object 203 within process space 201 which presents all defined interfaces of object 202 to process B. Stub code 210 is activated within process A, and proxy object 203 is linked to the stub code. When process B initiates an in-process function call on proxy object 203, the function call is marshalled through the process boundary by remoting code in proxy object 203 using the standard OLE/COM cross-process marshaller. Stub code 210 unmarshals the function call within process A, and executes the function call in-process on object 202 in process space 200. Return values in process A from object 202 are marshalled back through the process boundary by the stub code and returned from proxy object 203 to process B. Other processes wishing to share object 202 are similarly granted proxy/stub pairs for interfacing with object 202 via cross-process calls. The OLE cross-process marshaller maintains at least one reference on the shared object for each additional process that has a reference to it.
FIG. 2B illustrates the sharing of an object in which the object is created by an object server in DLL (dynamic link library) 205 appended to process A. The DLL provides a convenient way to implement in-process servers as needed. The shared object within the DLL is accessed in-process by process A, and accessed cross-process by process B as outlined with respect to FIG. 2A.
The above OLE/COM mechanism for sharing objects suffers from both performance and correctness problems. With regard to performance, all cross-process calls are much slower than in-process calls. The slowness is due to the need to marshal the function call and perform context switching between processes. Unfortunately, all processes, except the process that owns the shared object, access the shared object cross-process.
With regard to correctness, there exists a problem in managing the shutdown of an application or process which owns a shared object. All processes which are accessing the shared object cross-process require that the process which created the shared object not terminate as long as the shared object is needed. It is left to the programmer of the source application to be aware of this shutdown problem and take steps accordingly. If the source application leverages an in-process object server (e.g., via a dynamic link library) (DLL)) to create the objects, as shown in FIG. 2B, the objects are still accessible via cross-process calls through the source application. It is extremely difficult for the in-process server to keep the source application alive. The premature shutdown of a source application and its shared object can lead to data loss for other processes accessing the shared object.
One method for dealing with the shutdown problem is to have the original process determine when it cannot exit safely. The original process can then hide itself and stay running in the background. However, this is an unsatisfactory solution in terms of resources. For example, all resources, such as system memory, that are allocated to the original process may not be reclaimed until the original process exits. Further, another process may locate the hidden process, and attempt to reactivate the hidden process from an ill-defined state.
Another method for preventing premature shutdown of a shared object and its source process is to create a custom application communication protocol which enforces correct shutdown order. However, the use of a custom application protocol causes difficulty in a system that includes applications from multiple vendors, as it requires that each process have knowledge of every other process.
A third method for preventing premature shutdown of a source process and its shared object(s) is illustrated in FIG. 2C. All objects are created in a distinct process space 206 so that there is no application shutdown or communication issue. Objects 202 and 209 are instantiated within process space 206. Process A accesses the interfaces of object 209 via proxy object 207 and stub code 211. Process B accesses the interfaces of object 202 via proxy object 203 and stub code 210. Elements 204 and 208 represent the cross-process marshalling of function calls, for example via LRPC packets.
In FIG. 2C, process C acts as the object server for all shared objects. The shutdown of any process other than process C does not result in data loss for any other process, because all objects are owned by process C. Thus, process C can be maintained indefinitely to support the shared objects and alleviate the shutdown problem. The obvious disadvantage associated with the method of FIG. 2C is that all calls to the shared objects are performed as cross-process calls. Even in the common case where process A accesses what would normally be its own objects and no other processes share those objects, all process calls by process A that would previously have been made inprocess (e.g., under the mechanisms of FIGS. 2A-B) are now made crossprocess to process C under the mechanism of FIG. 2C. System performance is therefore extremely slow. No method exists for solving the shutdown problem without experiencing performance loss due to the expense of crossprocess calls.
The invention provides a method and apparatus for providing peer ownership of shared objects. In the invention, shared objects, or xe2x80x9cpeerxe2x80x9d objects, are implemented as a shell object with shared object state stored in shared memory. Each process that shares the object is granted a shell object within their process space which points to the object state in shared memory. All processes share equal access to the shared object, with no single process determining the lifetime of the shared object. The shutdown of any single process results in the termination of that process""s respective shell object, without the necessary termination of the shared object state in shared memory. There is therefore no shutdown problem. Further, performance is enhanced because all processes access the shared object state in shared memory in what is essentially an in-process call.
The shell object presents the interfaces of a given object, but maintains all object state in a data block in shared memory. A pointer is maintained in the shell object which points to the data block in shared memory, and all operations on the object state are performed in-process via this pointer. In one embodiment, the shell object also contains a reference count value controlled by the process containing the shell. When the reference count is zero, the shell object may be terminated. A separate reference count is maintained for the object state itself. The reference count of the object state is incremented for each shell object that points to it. When a shell object is terminated, the object state reference count is decremented by one. The object state in shared memory is only permitted to terminate when the object state reference count is zero, indicating that no corresponding shell objects remain in any process.
In an embodiment of the invention, a peer ownership manager acts as the object server for all shared objects whose object state resides in shared memory. The peer ownership manager may maintain the reference count for each object""s object state in shared memory, or the reference count may be stored within the object state itself. A global table is maintained within the peer ownership manager which contains the shared memory offset location of each object""s state referenced by the GID (global identifier number) of the object. For each process, a shell table is maintained in which existing shell objects for a given process are referenced by the offset value for the object""s state in shared memory. The shared memory offset remains the same regardless of process space. When necessary, such as to set a shell pointer for the corresponding object state, the shared memory offset value is resolved into a pointer value for the respective process space. Methods are provided for supporting object webs in shared memory, and for putting dynamically sized data and standard non-peer objects into shared objects in shared memory.